<template>
<!--  :style="containerStyle"-->
    <view class="x-color-picker" :class="{ 'color-picker--dark': darkMode }" style="width: 100%;" >
        <!-- 预设颜色 -->
        <view class="preset-colors" v-if="showPresets && false">
            <view class="preset-title">常用颜色</view>
            <view class="preset-grid">
                <view v-for="(color, index) in presetColors" :key="index" class="preset-item" :style="[{ backgroundColor: color }]" @click="selectPresetColor(color)">
                    <view v-if="color === currentHex" class="preset-selected">✓</view>
                </view>
            </view>
        </view>

        <!-- 历史颜色 -->
        <view class="history-colors" v-if="colorHistory.length > 0 && false">
            <view class="history-title">
                <text>最近使用</text>
                <text @click="clearColorHistory">清除</text>
            </view>
            <view class="history-grid">
                <view v-for="(color, index) in colorHistory" :key="index" class="history-item" :style="[{ backgroundColor: color }]" @click="selectPresetColor(color)">
                    <view v-if="color === currentHex" class="history-selected">✓</view>
                </view>
            </view>
        </view>

      <!-- 颜色预览和信息 -->
      <view class="color-info" style="margin-bottom: 0;">
        <!-- 颜色预览 -->
        <view class="color-preview" style="display: grid; grid-template-columns: 1fr 2fr; width: 100%">
          颜色预览：<view class="preview-current" :style="[{ backgroundColor: currentColorRgba }]"></view>
        </view>
      </view>

        <!-- 主色彩选择区域 -->
        <view class="color-main" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20rpx; margin-bottom: 0px;">
            <!-- 饱和度/亮度面板 -->
            <view class="saturation-panel" :style="[panelStyle, { backgroundColor: pureColor }, {padding: 0}]" @touchstart="onSaturationTouchStart" @touchmove="onSaturationTouchMove" @touchend="onTouchEnd"
                ref="saturationPanel">
                <!-- 白色渐变 -->
                <view class="saturation-white"></view>
                <!-- 黑色渐变 -->
                <view class="saturation-black"></view>
                <!-- 选择器指示点 -->
                <view class="saturation-cursor" :style="[cursorStyle, { left: saturationPosition.x + 'px', top: saturationPosition.y + 'px' }]"></view>
            </view>

          <div class="" style="display: flex;flex-direction: column; justify-content: space-around;">
            <!-- 色相滑条 -->
            <view class="hue-slider" :style="sliderStyle" @touchstart="onHueTouchStart" @touchmove="onHueTouchMove" @touchend="onTouchEnd">
              <view class="hue-track"></view>
              <view class="hue-cursor" :style="[{ left: huePosition + 'px' }]"></view>
            </view>

            <!-- 透明度滑条 -->
            <view v-if="showAlpha" class="alpha-slider" :style="sliderStyle" @touchstart="onAlphaTouchStart" @touchmove="onAlphaTouchMove" @touchend="onTouchEnd">
              <view class="alpha-checkerboard"></view>
              <view class="alpha-bg" :style="[{ background: alphaGradient }]"></view>
              <view class="alpha-cursor" :style="[{ left: alphaPosition + 'px' }]"></view>
            </view>
          </div>

        </view>

        <!-- 颜色预览和信息 -->
        <view class="color-info" v-if="false">
            <!-- 颜色预览 -->
            <view class="color-preview">
                <view class="preview-current" :style="[{ backgroundColor: currentColorRgba }]">
                    <view class="preview-checkerboard"></view>
                </view>
                <view class="preview-old" :style="[{ backgroundColor: initialColor }]"></view>
            </view>

            <!-- 颜色值输入 -->
            <view  class="color-inputs">
                <view class="input-tabs">
                    <text v-for="tab in inputTabs" :key="tab.key" class="input-tab" :class="{ active: activeInputTab === tab.key }" @click="activeInputTab = tab.key">
                        {{ tab.label }}
                    </text>
                </view>

                <!-- HEX 输入 -->
                <view v-if="activeInputTab === 'hex'" class="input-group">
                    <input class="color-input hex-input" v-model="hexInput" @input="onHexInput" @blur="validateHexInput" maxlength="7" placeholder="#000000" />
                </view>

                <!-- RGB 输入 -->
                <view v-if="activeInputTab === 'rgb'" class="input-row">
                    <view class="input-group">
                        <text class="input-label">R</text>
                        <input class="color-input" type="number" v-model.number="rgbInput.r" @input="onRgbInput" min="0" max="255" />
                    </view>
                    <view class="input-group">
                        <text class="input-label">G</text>
                        <input class="color-input" type="number" v-model.number="rgbInput.g" @input="onRgbInput" min="0" max="255" />
                    </view>
                    <view class="input-group">
                        <text class="input-label">B</text>
                        <input class="color-input" type="number" v-model.number="rgbInput.b" @input="onRgbInput" min="0" max="255" />
                    </view>
                    <view v-if="showAlpha" class="input-group">
                        <text class="input-label">A</text>
                        <input class="color-input" type="number" v-model.number="alphaInput" @input="onAlphaInputChange" min="0" max="100" />
                    </view>
                </view>

                <!-- HSL 输入 -->
                <view v-if="activeInputTab === 'hsl'" class="input-row">
                    <view class="input-group">
                        <text class="input-label">H</text>
                        <input class="color-input" type="number" v-model.number="hslInput.h" @input="onHslInput" min="0" max="360" />
                    </view>
                    <view class="input-group">
                        <text class="input-label">S</text>
                        <input class="color-input" type="number" v-model.number="hslInput.s" @input="onHslInput" min="0" max="100" />
                    </view>
                    <view class="input-group">
                        <text class="input-label">L</text>
                        <input class="color-input" type="number" v-model.number="hslInput.l" @input="onHslInput" min="0" max="100" />
                    </view>
                </view>
            </view>
        </view>

        <!-- 操作按钮 -->
        <view class="color-actions" v-if="false">
            <button class="action-btn cancel-btn" @click="onCancel">
                {{ cancelText }}
            </button>
            <button class="action-btn confirm-btn" @click="onConfirm">
                {{ confirmText }}
            </button>
        </view>
    </view>
</template>

<script>
    const PRESET_COLORS = [
        '#FF0000', '#FF8000', '#FFFF00', '#80FF00', '#00FF00', '#00FF80',
        '#00FFFF', '#0080FF', '#0000FF', '#8000FF', '#FF00FF', '#FF0080',
        '#000000', '#404040', '#808080', '#C0C0C0', '#FFFFFF', '#FF8080',
        '#FFB366', '#FFFF80', '#B3FF80', '#80FF80', '#80FFB3', '#80FFFF',
        '#80B3FF', '#8080FF', '#B380FF', '#FF80FF', '#FF80B3'
    ];

    const DEFAULT_OPTIONS = {
        width: uni.upx2px(375),
        padding: uni.upx2px(32),
        throttleDelay: 16,
        cursorSize: uni.upx2px(36),
        maxHistory: 8
    }


    export default {
        name: 'x-color-picker',
        props: {
            modelValue: {
                type: String,
                default: '#1B73CC'
            },
            showAlpha: {
                type: Boolean,
                default: true
            },
            showPresets: {
                type: Boolean,
                default: true
            },
            darkMode: {
                type: Boolean,
                default: false
            },
            saveHistory: {
                type: Boolean,
                default: true
            },
            cancelText: {
                type: String,
                default: '取消'
            },
            confirmText: {
                type: String,
                default: '确定'
            },
            options: {
                type: Object,
                default: () => DEFAULT_OPTIONS
            }
        },
        emits: ['update:modelValue', 'cancel', 'confirm', 'change'],
        data() {
            return {
                // 内部状态
                internalHsv: { h: 0, s: 100, v: 100 },
                internalRgb: { r: 255, g: 0, b: 0 },
                internalAlpha: 100,

                // 输入框状态
                hexInput: '#FF0000',
                rgbInput: { r: 255, g: 0, b: 0 },
                hslInput: { h: 0, s: 100, l: 50 },
                alphaInput: 100,

                // UI 状态
                activeInputTab: 'hex',
                initialColor: '#FF0000',
                colorHistory: [],

                // 位置信息
                saturationPosition: { x: 0, y: 0 },
                huePosition: 0,
                alphaPosition: 0,

                // 触摸状态
                isDragging: false,
                dragType: '',
                lastTouchTime: 0,

                // 缓存的DOM查询结果
                panelRect: null,
                hueRect: null,
                alphaRect: null
            }
        },
        computed: {
            // 合并配置选项
            mergedOptions() {
                return { ...DEFAULT_OPTIONS, ...this.options };
            },

            // 计算面板尺寸（内容区域宽度减去内边距）
            computedPanelSize() {
                const contentWidth = this.mergedOptions.width - (this.mergedOptions.padding * 2);
                return {
                    width: contentWidth,
                    height: contentWidth * 0.714 // 保持 560:400 的宽高比
                };
            },

            // 计算滑条宽度
            computedSliderWidth() {
                return this.mergedOptions.width - (this.mergedOptions.padding * 2);
            },

            // 容器样式
            containerStyle() {
                return {
                    width: this.mergedOptions.width + 'px',
                    padding: this.mergedOptions.padding + 'px'
                };
            },

            // 面板样式
            panelStyle() {
                return {
                    width: this.computedPanelSize.width + 'px',
                    height: this.computedPanelSize.height + 'px'
                };
            },

            // 指示点样式
            cursorStyle() {
                return {
                    width: this.mergedOptions.cursorSize + 'px',
                    height: this.mergedOptions.cursorSize + 'px'
                };
            },

            // 滑条样式
            sliderStyle() {
                return {
                    width: this.computedSliderWidth + 'px'
                };
            },

            // 预设颜色
            presetColors() {
                return PRESET_COLORS;
            },

            // 输入标签页
            inputTabs() {
                return [
                    { key: 'hex', label: 'HEX' },
                    { key: 'rgb', label: 'RGB' },
                    { key: 'hsl', label: 'HSL' }
                ];
            },

            // 当前HEX颜色
            currentHex() {
                return this.rgbToHex(this.internalRgb.r, this.internalRgb.g, this.internalRgb.b);
            },

            // 纯色（用于饱和度面板背景）
            pureColor() {
                return this.hsvToRgbString(this.internalHsv.h, 100, 100);
            },

            // 当前颜色的RGBA值
            currentColorRgba() {
                const { r, g, b } = this.internalRgb;
                const alpha = this.internalAlpha / 100;
                return `rgba(${r}, ${g}, ${b}, ${alpha})`;
            },

            // 透明度渐变背景
            alphaGradient() {
                const { r, g, b } = this.internalRgb;
                return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0), rgba(${r}, ${g}, ${b}, 1))`;
            }
        },
        watch: {
            modelValue: {
                handler(newVal, oldVal) {
                  // console.log('newVal', newVal)
                  // if(newVal === oldVal) return;
                    this.initialColor = newVal || 'rgba(242, 90, 39, 1)';
                    // if(newVal.indexOf('rgba') > -1) {
                    //
                    // }

                  const result = this.rgbaToHexAndAlpha(newVal);
                  this.internalAlpha = result.alpha * 100;
                  this.setColor(result.hex);
                  // console.log(this.internalAlpha, result );
                },
                immediate: true
            },
            // 监听配置变化，重新计算位置
            'mergedOptions.width': {
                handler() {
                    this.$nextTick(() => {
                        this.updateAllPositions();
                    });
                }
            }
        },
        mounted() {
            this.loadColorHistory();
        },
        methods: {
           rgbaToHexAndAlpha(rgbaString) {
              // 使用正则表达式提取 R, G, B, A 值
              const values = rgbaString.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);

              if (!values) {
                return { error: "Invalid RGBA string format." };
              }

              const r = parseInt(values[1]);
              const g = parseInt(values[2]);
              const b = parseInt(values[3]);
              const a = parseFloat(values[4]);

              // 将单个颜色分量转换为两位十六进制
              const toHex = (c) => {
                const hex = c.toString(16);
                return hex.length === 1 ? "0" + hex : hex;
              };

              // 组合成 6 位 Hex
              const hex6 = "#" + toHex(r) + toHex(g) + toHex(b);

              // 计算透明度百分比
              const opacityPercent = Math.round(a * 100) + "%";

              // 计算用于 8 位 Hex 的 Alpha 值
              const alphaHex = toHex(Math.round(a * 255));
              const hex8 = "#" + toHex(r) + toHex(g) + toHex(b) + alphaHex;

              return {
                hex: hex6,          // 6位Hex
                hex8: hex8,         // 8位Hex
                opacity: opacityPercent, // 透明度百分比
                alpha: a            // 原始Alpha值
              };
            },
            // ========== 颜色设置 ==========
            setColor(color) {
                const rgb = this.hexToRgb(color);
                const hsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);
                const hsl = this.rgbToHsl(rgb.r, rgb.g, rgb.b);

                this.internalRgb = rgb;
                this.internalHsv = hsv;

                // 更新输入框
                this.hexInput = color;
                this.rgbInput = { ...rgb };
                this.hslInput = hsl;

                this.updateAllPositions();
            },

            // 更新所有位置
            updateAllPositions() {
                const { h, s, v } = this.internalHsv;

                // 色相位置
                this.huePosition = (h / 360) * this.computedSliderWidth;

                // 饱和度/亮度位置
                this.saturationPosition.x = (s / 100) * this.computedPanelSize.width;
                this.saturationPosition.y = ((100 - v) / 100) * this.computedPanelSize.height;

                // 透明度位置
                this.alphaPosition = (this.internalAlpha / 100) * this.computedSliderWidth;
            },

            // ========== 预设颜色相关 ==========
            selectPresetColor(color) {
                this.setColor(color);
                this.emitChange();
            },

            // 加载颜色历史
            loadColorHistory() {
                if (this.saveHistory) {
                    this.colorHistory = uni.getStorageSync('colorPickerHistory') || [];
                }
            },

            // 清除颜色历史
            clearColorHistory() {
                this.colorHistory = []
                uni.removeStorageSync('colorPickerHistory')
            },

            // 保存颜色历史
            saveColorHistory() {
                const color = this.currentHex;
                let history = [...this.colorHistory];

                // 移除已存在的相同颜色
                history = history.filter(c => c !== color);

                // 添加到开头
                history.unshift(color);

                // 限制历史记录数量
                if (history.length > this.mergedOptions.maxHistory) {
                    history = history.slice(0, this.mergedOptions.maxHistory);
                }

                if (this.saveHistory) {
                    this.colorHistory = history;
                    uni.setStorageSync('colorPickerHistory', history);
                }
            },

            // ========== 触摸事件处理 ==========
            onSaturationTouchStart(e) {
                this.startDragging('saturation', e);
                this.updateSaturationFromTouch(e);
            },

            onSaturationTouchMove(e) {
                if (this.isDragging && this.dragType === 'saturation') {
                    this.throttledUpdateSaturation(e);
                }
            },

            onHueTouchStart(e) {
                this.startDragging('hue', e);
                this.updateHueFromTouch(e);
            },

            onHueTouchMove(e) {
                if (this.isDragging && this.dragType === 'hue') {
                    // this.throttledUpdateHue(e);
                  this.updateHueFromTouch(e);
                }
            },

            onAlphaTouchStart(e) {
                this.startDragging('alpha', e);
                this.updateAlphaFromTouch(e);
            },

            onAlphaTouchMove(e) {
                if (this.isDragging && this.dragType === 'alpha') {
                    this.throttledUpdateAlpha(e);
                }
            },

            onTouchEnd() {
                this.isDragging = false;
                this.dragType = '';
                this.clearRectCache();
            },

            // 开始拖拽
            startDragging(type, e) {
                this.isDragging = true;
                this.dragType = type;
            },

            // ========== 节流更新函数 ==========
            throttledUpdateSaturation(e) {
                return this.throttle(() => this.updateSaturationFromTouch(e), this.mergedOptions.throttleDelay);
            },

            throttledUpdateHue(e) {
                return this.throttle(() => this.updateHueFromTouch(e), 0);//this.mergedOptions.throttleDelay);
            },

            throttledUpdateAlpha(e) {
                return this.throttle(() => this.updateAlphaFromTouch(e), this.mergedOptions.throttleDelay);
            },

            // 节流函数
            throttle(func, delay) {
                const now = Date.now();
                if (now - this.lastTouchTime >= delay) {
                    this.lastTouchTime = now;
                    return func();
                }
            },

            // ========== 位置更新函数 ==========
            updateSaturationFromTouch(e) {
                const touch = e.touches[0] || e.changedTouches[0];

                if (this.panelRect) {
                    this.updateSaturationPosition(touch, this.panelRect);
                } else {
                    this.queryRect('.saturation-panel', (rect) => {
                        this.panelRect = rect;
                        this.updateSaturationPosition(touch, rect);
                    });
                }
            },

            updateSaturationPosition(touch, rect) {
                const x = Math.max(0, Math.min(touch.clientX - rect.left, this.computedPanelSize.width));
                const y = Math.max(0, Math.min(touch.clientY - rect.top, this.computedPanelSize.height));

                this.saturationPosition.x = x;
                this.saturationPosition.y = y;

                const s = (x / this.computedPanelSize.width) * 100;
                const v = ((this.computedPanelSize.height - y) / this.computedPanelSize.height) * 100;

                this.internalHsv.s = Math.round(s);
                this.internalHsv.v = Math.round(v);

                this.updateColorFromHsv();
            },

            updateHueFromTouch(e) {
                const touch = e.touches[0] || e.changedTouches[0];

                if (this.hueRect) {
                    this.updateHuePosition(touch, this.hueRect);
                } else {
                    this.queryRect('.hue-slider', (rect) => {
                        this.hueRect = rect;
                        this.updateHuePosition(touch, rect);
                    });
                }
            },

            updateHuePosition(touch, rect) {
                const x = Math.max(0, Math.min(touch.clientX - rect.left, this.computedSliderWidth));
                this.huePosition = x;

                const h = (x / this.computedSliderWidth) * 360;
                this.internalHsv.h = Math.round(h);

                // this.updateColorFromHsv();
                this.throttledUpdateColorFromHsv()
            },

            updateAlphaFromTouch(e) {
                const touch = e.touches[0] || e.changedTouches[0];

                if (this.alphaRect) {
                    this.updateAlphaPosition(touch, this.alphaRect);
                } else {
                    this.queryRect('.alpha-slider', (rect) => {
                        this.alphaRect = rect;
                        this.updateAlphaPosition(touch, rect);
                    });
                }
            },

            updateAlphaPosition(touch, rect) {
                const x = Math.max(0, Math.min(touch.clientX - rect.left, this.computedSliderWidth));
                this.alphaPosition = x;

                const alpha = (x / this.computedSliderWidth) * 100;
                this.internalAlpha = Math.round(alpha);
                this.alphaInput = this.internalAlpha;

                setTimeout(() => {
                    this.emitChange();
                }, 10);
            },

            // DOM查询封装
            queryRect(selector, callback) {
                uni.createSelectorQuery().in(this).select(selector).boundingClientRect(callback).exec();
            },

            // 清除DOM查询缓存
            clearRectCache() {
                this.panelRect = null;
                this.hueRect = null;
                this.alphaRect = null;
            },

            // ========== 颜色更新 ==========
            updateColorFromHsv() {
                const { h, s, v } = this.internalHsv;
                this.internalRgb = this.hsvToRgb(h, s, v);

                // 更新输入框
                this.hexInput = this.currentHex;
                this.rgbInput = { ...this.internalRgb };
                this.hslInput = this.rgbToHsl(this.internalRgb.r, this.internalRgb.g, this.internalRgb.b);

                this.emitChange();
            },

            throttledUpdateColorFromHsv(e) {
              return this.throttle(() => this.updateColorFromHsv(e), this.mergedOptions.throttleDelay);
            },

            // ========== 输入事件处理 ==========
            onHexInput() {
                if (this.isValidHex(this.hexInput)) {
                    const rgb = this.hexToRgb(this.hexInput);
                    const hsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);

                    this.internalRgb = rgb;
                    this.internalHsv = hsv;
                    this.rgbInput = { ...rgb };
                    this.hslInput = this.rgbToHsl(rgb.r, rgb.g, rgb.b);

                    this.updateAllPositions();
                    this.emitChange();
                }
            },

            validateHexInput() {
                if (!this.isValidHex(this.hexInput)) {
                    this.hexInput = this.currentHex;
                }
            },

            onRgbInput() {
                // 验证和限制输入值
                this.rgbInput.r = this.clamp(this.rgbInput.r || 0, 0, 255);
                this.rgbInput.g = this.clamp(this.rgbInput.g || 0, 0, 255);
                this.rgbInput.b = this.clamp(this.rgbInput.b || 0, 0, 255);

                this.internalRgb = { ...this.rgbInput };
                this.internalHsv = this.rgbToHsv(this.internalRgb.r, this.internalRgb.g, this.internalRgb.b);

                this.hexInput = this.currentHex;
                this.hslInput = this.rgbToHsl(this.internalRgb.r, this.internalRgb.g, this.internalRgb.b);

                this.updateAllPositions();
                this.emitChange();
            },

            onHslInput() {
                // 验证和限制输入值
                this.hslInput.h = this.clamp(this.hslInput.h || 0, 0, 360);
                this.hslInput.s = this.clamp(this.hslInput.s || 0, 0, 100);
                this.hslInput.l = this.clamp(this.hslInput.l || 0, 0, 100);

                const rgb = this.hslToRgb(this.hslInput.h, this.hslInput.s, this.hslInput.l);
                this.internalRgb = rgb;
                this.internalHsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);

                this.hexInput = this.currentHex;
                this.rgbInput = { ...rgb };

                this.updateAllPositions();
                this.emitChange();
            },

            onAlphaInputChange() {
                this.alphaInput = this.clamp(this.alphaInput || 0, 0, 100);
                this.internalAlpha = this.alphaInput;
                this.alphaPosition = (this.internalAlpha / 100) * this.computedSliderWidth;
                this.emitChange();
            },

            // ========== 工具函数 ==========
            clamp(value, min, max) {
                return Math.max(min, Math.min(max, parseInt(value) || 0));
            },

            // 发出变化事件
            emitChange() {
                const color = {
                    hex: this.currentHex,
                    rgb: this.internalRgb,
                    hsv: this.internalHsv,
                    hsl: this.hslInput,
                    alpha: this.internalAlpha,
                    rgba: this.currentColorRgba
                };
                this.$emit('change', color);
            },

            // ========== 颜色转换函数 ==========
            hsvToRgb(h, s, v) {
                h = h / 360;
                s = s / 100;
                v = v / 100;

                const i = Math.floor(h * 6);
                const f = h * 6 - i;
                const p = v * (1 - s);
                const q = v * (1 - f * s);
                const t = v * (1 - (1 - f) * s);

                let r, g, b;
                switch (i % 6) {
                    case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                    case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                    case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                    case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                    case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                    case 5:
                        r = v;
                        g = p;
                        b = q;
                        break;
                }

                return {
                    r: Math.round(r * 255),
                    g: Math.round(g * 255),
                    b: Math.round(b * 255)
                };
            },

            hsvToRgbString(h, s, v) {
                const rgb = this.hsvToRgb(h, s, v);
                return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
            },

            rgbToHsv(r, g, b) {
                r /= 255;
                g /= 255;
                b /= 255;

                const max = Math.max(r, g, b);
                const min = Math.min(r, g, b);
                const diff = max - min;

                let h = 0;
                const s = max === 0 ? 0 : diff / max;
                const v = max;

                if (diff !== 0) {
                    if (max === r) {
                        h = ((g - b) / diff) % 6;
                    } else if (max === g) {
                        h = (b - r) / diff + 2;
                    } else {
                        h = (r - g) / diff + 4;
                    }
                }

                return {
                    h: Math.round((h < 0 ? h + 6 : h) * 60),
                    s: Math.round(s * 100),
                    v: Math.round(v * 100)
                };
            },

            rgbToHsl(r, g, b) {
                r /= 255;
                g /= 255;
                b /= 255;

                const max = Math.max(r, g, b);
                const min = Math.min(r, g, b);
                const diff = max - min;
                const sum = max + min;

                let h = 0;
                let s = 0;
                const l = sum / 2;

                if (diff !== 0) {
                    s = l > 0.5 ? diff / (2 - sum) : diff / sum;

                    if (max === r) {
                        h = ((g - b) / diff) + (g < b ? 6 : 0);
                    } else if (max === g) {
                        h = (b - r) / diff + 2;
                    } else {
                        h = (r - g) / diff + 4;
                    }
                    h /= 6;
                }

                return {
                    h: Math.round(h * 360),
                    s: Math.round(s * 100),
                    l: Math.round(l * 100)
                };
            },

            hslToRgb(h, s, l) {
                h /= 360;
                s /= 100;
                l /= 100;

                const c = (1 - Math.abs(2 * l - 1)) * s;
                const x = c * (1 - Math.abs((h * 6) % 2 - 1));
                const m = l - c / 2;

                let r, g, b;

                if (0 <= h && h < 1 / 6) {
                    r = c;
                    g = x;
                    b = 0;
                } else if (1 / 6 <= h && h < 2 / 6) {
                    r = x;
                    g = c;
                    b = 0;
                } else if (2 / 6 <= h && h < 3 / 6) {
                    r = 0;
                    g = c;
                    b = x;
                } else if (3 / 6 <= h && h < 4 / 6) {
                    r = 0;
                    g = x;
                    b = c;
                } else if (4 / 6 <= h && h < 5 / 6) {
                    r = x;
                    g = 0;
                    b = c;
                } else {
                    r = c;
                    g = 0;
                    b = x;
                }

                return {
                    r: Math.round((r + m) * 255),
                    g: Math.round((g + m) * 255),
                    b: Math.round((b + m) * 255)
                };
            },

            rgbToHex(r, g, b) {
                return '#' + [r, g, b].map(x => {
                    const hex = x.toString(16);
                    return hex.length === 1 ? '0' + hex : hex;
                }).join('').toUpperCase();
            },

            hexToRgb(hex) {
                const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
                return result ? {
                    r: parseInt(result[1], 16),
                    g: parseInt(result[2], 16),
                    b: parseInt(result[3], 16)
                } : { r: 255, g: 0, b: 0 };
            },

            isValidHex(hex) {
                return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(hex);
            },

            // ========== 按钮事件 ==========
            onCancel() {
                this.setColor(this.initialColor);
                this.$emit('cancel');
            },

            onConfirm() {
                this.saveColorHistory();
                const color = {
                    hex: this.currentHex,
                    rgb: this.internalRgb,
                    hsv: this.internalHsv,
                    hsl: this.hslInput,
                    alpha: this.internalAlpha,
                    rgba: this.currentColorRgba
                };
                this.$emit('confirm', color);
                this.$emit('update:modelValue', this.currentHex);
            }
        }
    }
</script>

<style scoped>
    .x-color-picker {
        background: #ffffff;
        border-radius: 24rpx;
        box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
        margin: 0 auto;
        box-sizing: border-box;
    }

    .color-picker--dark {
        background: #1a1a1a;
        color: #ffffff;
    }

    /* ========== 预设颜色 ========== */
    .preset-colors,
    .history-colors {
        margin-bottom: 40rpx;
    }

    .preset-title,
    .history-title {
        font-size: 28rpx;
        color: #666666;
        margin-bottom: 16rpx;
        font-weight: 500;
    }

    .history-title {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    .history-title text:last-child {
        color: #ff0000;
        font-size: 26rpx;
    }

    .color-picker--dark .preset-title,
    .color-picker--dark .history-title {
        color: #cccccc;
    }

    .preset-grid,
    .history-grid {
        display: flex;
        flex-wrap: wrap;
        gap: 12rpx;
    }

    .preset-item,
    .history-item {
        width: 56rpx;
        height: 56rpx;
        border-radius: 12rpx;
        border: 3rpx solid #ffffff;
        box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
        cursor: pointer;
        transition: all 0.2s ease;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
    }

    .preset-item:active,
    .history-item:active {
        transform: scale(0.95);
    }

    .preset-selected,
    .history-selected {
        color: #ffffff;
        font-size: 24rpx;
        font-weight: bold;
        text-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.5);
    }

    /* ========== 主色彩选择区域 ========== */
    .color-main {
        margin-bottom: 40rpx;
    }

    .saturation-panel {
        position: relative;
        border-radius: 16rpx;
        overflow: hidden;
        margin-bottom: 32rpx;
        box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
        cursor: crosshair;
    }

    .saturation-white {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(to right, #ffffff, transparent);
    }

    .saturation-black {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(to bottom, transparent, #000000);
    }

    .saturation-cursor {
        position: absolute;
        border: 4rpx solid #ffffff;
        border-radius: 50%;
        box-shadow: 0 0 12rpx rgba(0, 0, 0, 0.4), inset 0 0 4rpx rgba(0, 0, 0, 0.2);
        transform: translate(-50%, -50%);
        pointer-events: none;
        transition: transform 0.1s ease;
    }

    .saturation-cursor:active {
        transform: translate(-50%, -50%) scale(1.2);
    }

    /* ========== 滑条样式 ========== */
    .hue-slider,
    .alpha-slider {
        height: 48rpx;
        position: relative;
        border-radius: 24rpx;
        margin-bottom: 24rpx;
        cursor: pointer;
        box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
    }

    .hue-track {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: linear-gradient(to right,
                #ff0000 0%,
                #ffff00 16.66%,
                #00ff00 33.33%,
                #00ffff 50%,
                #0000ff 66.66%,
                #ff00ff 83.33%,
                #ff0000 100%);
        border-radius: 24rpx;
    }

    .hue-cursor,
    .alpha-cursor {
        position: absolute;
        top: -8rpx;
        width: 32rpx;
        height: 64rpx;
        background: #ffffff;
        border: 3rpx solid #dddddd;
        border-radius: 8rpx;
        box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
        transform: translateX(-50%);
        pointer-events: none;
        transition: all 0.1s ease;
    }

    .hue-cursor:active,
    .alpha-cursor:active {
        transform: translateX(-50%) scale(1.1);
    }

    /* ========== 透明度滑条 ========== */
    .alpha-checkerboard {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-image:
            linear-gradient(45deg, #cccccc 25%, transparent 25%),
            linear-gradient(-45deg, #cccccc 25%, transparent 25%),
            linear-gradient(45deg, transparent 75%, #cccccc 75%),
            linear-gradient(-45deg, transparent 75%, #cccccc 75%);
        background-size: 16rpx 16rpx;
        background-position: 0 0, 0 8rpx, 8rpx -8rpx, -8rpx 0;
        border-radius: 24rpx;
    }

    .alpha-bg {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 24rpx;
    }

    /* ========== 颜色信息区域 ========== */
    .color-info {
        display: flex;
        gap: 32rpx;
        margin-bottom: 40rpx;
    }

    .color-preview {
        width: 160rpx;
        flex-shrink: 0;
    }

    .preview-current,
    .preview-old {
        width: 100%;
        height: 60rpx;
        border-radius: 12rpx;
        position: relative;
        overflow: hidden;
        border: 2rpx solid #eeeeee;
    }

    .preview-current {
        margin-bottom: 16rpx;
    }

    .preview-checkerboard {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-image:
            linear-gradient(45deg, #eeeeee 25%, transparent 25%),
            linear-gradient(-45deg, #eeeeee 25%, transparent 25%),
            linear-gradient(45deg, transparent 75%, #eeeeee 75%),
            linear-gradient(-45deg, transparent 75%, #eeeeee 75%);
        background-size: 12rpx 12rpx;
        background-position: 0 0, 0 6rpx, 6rpx -6rpx, -6rpx 0;
    }


    /* ========== 颜色输入 ========== */
    .color-inputs {
        flex: 1;
        min-width: 0;
    }

    .input-tabs {
        display: flex;
        margin-bottom: 20rpx;
        background: #f8f8f8;
        border-radius: 12rpx;
        padding: 4rpx;
    }

    .color-picker--dark .input-tabs {
        background: #2a2a2a;
    }

    .input-tab {
        flex: 1;
        text-align: center;
        padding: 12rpx 8rpx;
        font-size: 26rpx;
        color: #666666;
        border-radius: 8rpx;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .input-tab.active {
        background: #ffffff;
        color: #333333;
        box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
    }

    .color-picker--dark .input-tab.active {
        background: #1a1a1a;
        color: #ffffff;
    }

    .input-group {
        margin-bottom: 20rpx;
    }

    .input-row {
        display: flex;
        gap: 16rpx;
    }

    .input-row .input-group {
        flex: 1;
        margin-bottom: 0;
    }

    .input-label {
        display: block;
        font-size: 24rpx;
        color: #666666;
        margin-bottom: 8rpx;
        font-weight: 500;
    }

    .color-picker--dark .input-label {
        color: #cccccc;
    }

    .color-input {
        width: 100%;
        height: 64rpx;
        padding: 0 16rpx;
        border: 2rpx solid #eeeeee;
        border-radius: 12rpx;
        font-size: 28rpx;
        text-align: center;
        box-sizing: border-box;
        transition: all 0.2s ease;
        background: #ffffff;
    }

    .color-picker--dark .color-input {
        background: #2a2a2a;
        border-color: #444444;
        color: #ffffff;
    }

    .color-input:focus {
        border-color: #007aff;
        outline: none;
        box-shadow: 0 0 0 4rpx rgba(0, 122, 255, 0.1);
    }

    .hex-input {
        font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
        text-transform: uppercase;
    }

    /* ========== 操作按钮 ========== */
    .color-actions {
        display: flex;
        gap: 24rpx;
        margin-top: 40rpx;
    }

    .action-btn {
        flex: 1;
        height: 88rpx;
        line-height: 88rpx;
        text-align: center;
        border-radius: 16rpx;
        font-size: 32rpx;
        font-weight: 500;
        border: none;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .cancel-btn {
        background: #f8f8f8;
        color: #666666;
    }

    .color-picker--dark .cancel-btn {
        background: #2a2a2a;
        color: #cccccc;
    }

    .confirm-btn {
        background: linear-gradient(135deg, #007aff, #0056cc);
        color: #ffffff;
        box-shadow: 0 4rpx 16rpx rgba(0, 122, 255, 0.3);
    }

    .action-btn:active {
        transform: scale(0.98);
    }

    .cancel-btn:active {
        background: #eeeeee;
    }

    .color-picker--dark .cancel-btn:active {
        background: #1a1a1a;
    }

    .confirm-btn:active {
        box-shadow: 0 2rpx 8rpx rgba(0, 122, 255, 0.4);
    }
</style>
